import static org.junit.Assert.*;

import java.math.BigDecimal;

import org.junit.Test;


public class testCompMeth {
	
	
	public static IFunction fid = new IFunction() {

		@Override
		public double compute(double x) {
			return x;
		}
	};

	public static IFunction fidd = new IFunction() {

		@Override
		public double compute(double x) {
			return 1;
		}
	};

	public static IFunction fsq = new IFunction() {

		@Override
		public double compute(double x) {
			return x * x;
		}
	};

	public static IFunction fsqd = new IFunction() {

		@Override
		public double compute(double x) {
			return 2 * x;
		}
	};

	public static Object[][] tests = new Object[][] {
		{0.0,3.5,fsq,14.2917},
		{0.0,3.5,fid,6.125},
	};
	
	@Test
	public void testAitken() {
		//System.out.println("WARNING, THIS IS A DUMB TEST!");
		int n = 100;
		BigDecimal[] series = new BigDecimal[n];
		double x = 0;
		for (int i = 0; i < n; i++) {
			x += (1 / (double) (i * 2 + 1)) * Math.pow(-1, i);
			series[i] = bd(x);
		}
		double tol = 0.001;
		
		BigDecimal[] res = Algs.aitken(series, bd(tol), n-3);
		
//		for (int i = 0; i < res.length; i++) {
//			System.out.println(i + ")" + res[i]);
//		}
//		System.out.println(Math.PI / 4);
		assertTrue(res[res.length - 2].subtract(bd(Math.PI/4)).abs()
				.compareTo(bd(tol)) < 0);
	}

	@Test
	public void testrichardson() {
		//System.out.println("WARNING, THIS IS A DUMB TEST!");
		int n = 100;
		BigDecimal[] series = new BigDecimal[n];
		for (int i = 0; i < n; i++) {
			series[i] = Algs.numericIntegration(i+1, fid, bd(0), bd(3.5));
		}
		
		
		double tol = 0.000001;
		
		int s = 6;


		BigDecimal[] res = Algs.richardson(series, bd(tol), n - 2, s);
//		for (int i = 0; i < res.length-1; i++) {
//			System.out.println("series:" + series[i]+" accelerated: "+res[i] +" err: "+series[i].subtract(res[i]).abs());
//		}
//		System.out.println(Math.PI / 4);
		assertTrue(res[res.length - 2].subtract(bd(6.125)).abs()
				.compareTo(bd(tol)) < 0);
	}

	public static void testBlindSearch() {
		double x0 = -5.2;
		double h = 0.5;
		double[] ab = Algs.blindSearch(fid, h, x0);
		for (int i = 0; i < ab.length; i++) {
			System.out.println(ab[i]);
		}
	}

	@Test
	public void testBoole() {
		
		boolean allworked = true;
		for (int i = 0; i < tests.length; i++) {			
			double a = (Double)tests[i][0];
			double h = (Double)tests[i][1] - a;
			IFunction f = (IFunction)tests[i][2];
			BigDecimal expected = bd((Double)tests[i][3]);
			
			BigDecimal res = Algs.booleIntegration(bd(a), bd(h), f);
			
			//System.out.println(res+" : "+expected +  " : " + res.subtract(expected).abs());
			
			allworked = allworked && res.subtract(expected).abs().compareTo(BigDecimal.ONE) < 0; 
		}
		assertTrue(allworked);
	}

	public static void testHorner() {

		double[] num = { 19, 3, 6, 7, -3, 4 };

		
		System.out.println(Algs.horner(num, 2.41));

	}

	public static void testNC() {

		System.out.println(Algs.booleIntegration(bd(1), bd(2.5), fid));

	}

	@Test
	public void testNumericIntegration() {
		
		boolean allworked = true;
		int m = 1;
		for (int i = 0; i < tests.length; i++) {			
			double a = (Double)tests[i][0];
			double b = (Double)tests[i][1];
			IFunction f = (IFunction)tests[i][2];
			BigDecimal expected = bd((Double)tests[i][3]);
			
			BigDecimal res = Algs.numericIntegration(m, f, bd(a), bd(b));
			
			//System.out.println(res+" : "+expected +  " : " + res.subtract(expected).abs());
			
			allworked = allworked && res.subtract(expected).abs().compareTo(BigDecimal.ONE) < 0; 
		}
		assertTrue(allworked);
	}

	@Test
	public void testAddaptiveNumericIntegration() {

		boolean allworked = true;
		double tol = 0.01;
		for (int i = 0; i < tests.length; i++) {			
			double a = (Double)tests[i][0];
			double b = (Double)tests[i][1];
			IFunction f = (IFunction)tests[i][2];
			BigDecimal expected = bd((Double)tests[i][3]);
			
			BigDecimal[] res = Algs.AddaptiveNumericIntegration(bd(tol), f, bd(a), bd(b));
			
			System.out.println(res[0]+" : "+expected +  " : " + res[0].subtract(expected).abs());
			
			allworked = allworked && res[0].subtract(expected).abs().compareTo(bd(tol)) < 0; 
		}
		assertTrue(allworked);
		
		// Answer needs to be 5.625
	}

	public static void testNR() {
		System.out.println(Algs.newtonRaphson(fsq, fsqd, -5.5, 1, 0.01));
	}

	public static void testSecant() {
		System.out.println(Algs.secant(fsq, fsqd, -5.5, 1, 0.001));
	}

	public static void testBiSection() {

		IFunction f = new IFunction() {

			@Override
			public double compute(double x) {

				return x + 1;
			}
		};

		double[] biSection = Algs.biSection(0.1, f, -4, 2);

		System.out.println("The error is " + biSection[0]
				+ " The aproximation is " + biSection[1]);
	}
	
	private static BigDecimal bd(double d) {
		return new BigDecimal(Double.toString(d));
	}

}
